package algorithm;

import utils.DateUtils;
import utils.PrintlnUtils;

import java.util.ArrayList;

/*
如何轻松写出正确的链表代码？
https://blog.csdn.net/ChinaDragon10/article/details/109438505
 */
public class TestLinkTable {
    private static final int ARRAY_LENGTH = 10_000_000;

    public static void main(String[] args) {
        ArrayList<Integer> numbers = new ArrayList<>();
        for (int i = 0; i < ARRAY_LENGTH; i++) {
            numbers.add(i);
        }

        int fixeeValue = 40_000_000;

//        int elementIndex1Result = elementIndex1(numbers, fixeeValue);
//        PrintlnUtils.println("elementIndex1Result = " + elementIndex1Result);
        /*
            elementIndex1 开始时间 2022-02-15｜09:37:01  startTime2 = 1644889021694

            elementIndex1 结束时间 2022-02-15｜09:37:01  endTime2   = 1644889021753

            elementIndex1 耗时 59 毫秒

            elementIndex1 耗时 0 秒

            elementIndex1Result = -1

         */

        int elementIndex2Result = elementIndex2(numbers, fixeeValue);
        PrintlnUtils.println("elementIndex2Result = " + elementIndex2Result);
        /*
            elementIndex2 开始时间 2022-02-15｜09:38:43  startTime2 = 1644889123796

            elementIndex2 结束时间 2022-02-15｜09:38:43  endTime2   = 1644889123852

            elementIndex2 耗时 56 毫秒

            elementIndex2 耗时 0 秒

            elementIndex2Result = -1

         */


        //当然，这只是为了举例说明哨兵的作用，你写代码的时候千万不要写第二段那样的代码，因为可读性太差了。大部分情况下，我们并不需要如此追求极致的性能。


    }


    /**
     * 在数组numbers中，查找value，返回value所在的位置
     *
     * @param value
     * @return
     */
    private static int elementIndex1(ArrayList<Integer> numbers, int value) {

        long startTime2 = System.currentTimeMillis();
        PrintlnUtils.println("elementIndex1 开始时间 " + DateUtils.timestamp2FormatedStr(startTime2) + "  startTime2 = " + startTime2);


        if (numbers == null || numbers.isEmpty()) {
            return -1;
        }

        int size = numbers.size();
        int i = 0;
        while (i < size) {
            if (numbers.get(i) == value) {

                long endTime2 = System.currentTimeMillis();
                PrintlnUtils.println("elementIndex1 结束时间 " + DateUtils.timestamp2FormatedStr(endTime2) + "  endTime2   = " + endTime2);

                long countMilisTime2 = endTime2 - startTime2;
                PrintlnUtils.println("elementIndex1 耗时 " + countMilisTime2 + " 毫秒");

                int countTime2 = (int) (countMilisTime2 * 1.0 / 1000);
                PrintlnUtils.println("elementIndex1 耗时 " + countTime2 + " 秒");

                return i;
            }

            ++i;
        }

       /*
            int i = 0;
            for (; i < size; i++) {
                if (numbers.get(i) == value) {
                    return i;
                }
            }

        */

        long endTime2 = System.currentTimeMillis();
        PrintlnUtils.println("elementIndex1 结束时间 " + DateUtils.timestamp2FormatedStr(endTime2) + "  endTime2   = " + endTime2);

        long countMilisTime2 = endTime2 - startTime2;
        PrintlnUtils.println("elementIndex1 耗时 " + countMilisTime2 + " 毫秒");

        int countTime2 = (int) (countMilisTime2 * 1.0 / 1000);
        PrintlnUtils.println("elementIndex1 耗时 " + countTime2 + " 秒");
        return -1;
    }

    private static int elementIndex2(ArrayList<Integer> numbers, int value) {
        long startTime2 = System.currentTimeMillis();
        PrintlnUtils.println("elementIndex2 开始时间 " + DateUtils.timestamp2FormatedStr(startTime2) + "  startTime2 = " + startTime2);

        if (numbers == null || numbers.isEmpty()) {
            return -1;
        }

        int size = numbers.size();
        int tempIndex = size - 1;

        //这里因为要将numbers.get(tempIndex)的值替换成key，所以要特殊处理这个值
        if (numbers.get(tempIndex) == value) {
            long endTime2 = System.currentTimeMillis();
            PrintlnUtils.println("elementIndex2 结束时间 " + DateUtils.timestamp2FormatedStr(endTime2) + "  endTime2   = " + endTime2);

            long countMilisTime2 = endTime2 - startTime2;
            PrintlnUtils.println("elementIndex2 耗时 " + countMilisTime2 + " 毫秒");

            int countTime2 = (int) (countMilisTime2 * 1.0 / 1000);
            PrintlnUtils.println("elementIndex2 耗时 " + countTime2 + " 秒");
            return tempIndex;
        }



        int temp = numbers.get(tempIndex);
        numbers.set(tempIndex, value);

        int i = 0;
        //while 循环比起代码一，少了i<n这个比较操作
        while (numbers.get(i) != value) {
            ++i;
        }

        //恢复numbers.get(tempIndex)原来的值,
        numbers.set(tempIndex, temp);

        if (i == tempIndex) {
            // 如果i == tempIndex 说明，在0...size-2之间都没有key，所以返回-1

            long endTime2 = System.currentTimeMillis();
            PrintlnUtils.println("elementIndex2 结束时间 " + DateUtils.timestamp2FormatedStr(endTime2) + "  endTime2   = " + endTime2);

            long countMilisTime2 = endTime2 - startTime2;
            PrintlnUtils.println("elementIndex2 耗时 " + countMilisTime2 + " 毫秒");

            int countTime2 = (int) (countMilisTime2 * 1.0 / 1000);
            PrintlnUtils.println("elementIndex2 耗时 " + countTime2 + " 秒");

            return -1;

        }

        long endTime2 = System.currentTimeMillis();
        PrintlnUtils.println("elementIndex2 结束时间 " + DateUtils.timestamp2FormatedStr(endTime2) + "  endTime2   = " + endTime2);

        long countMilisTime2 = endTime2 - startTime2;
        PrintlnUtils.println("elementIndex2 耗时 " + countMilisTime2 + " 毫秒");

        int countTime2 = (int) (countMilisTime2 * 1.0 / 1000);
        PrintlnUtils.println("elementIndex2 耗时 " + countTime2 + " 秒");

        return i;
    }
}
